home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 2000 October: Mac OS SDK / Dev.CD Oct 00 SDK1.toast / Development Kits / Mac OS / Multiprocessing 2.1v2 SDK / Sample Code / CloseViewMP ƒ / .c / µApp.c < prev   
Encoding:
C/C++ Source or Header  |  2000-05-25  |  29.9 KB  |  1,181 lines  |  [TEXT/CWIE]

  1. /**\
  2. |**|    µApp.c
  3. \**/
  4.  
  5. /**\
  6. |**| ==============================================================================
  7. |**| COMPILER DIRECTIVES
  8. |**| ==============================================================================
  9. \**/
  10.  
  11. #define kMaxTasks 64
  12.  
  13. #define SystemSevenOrLater        1
  14. #define DEBUGSTRINGS 1
  15.  
  16. /**\
  17. |**| ==============================================================================
  18. |**| INCLUDES
  19. |**| ==============================================================================
  20. \**/
  21.  
  22. #ifndef USE_PRECOMPILED_HEADER
  23. #include "myHeaders.i"
  24. #endif
  25.  
  26. #include <Devices.h>
  27. #include <Fonts.h>
  28. #include <CodeFragments.h>
  29. #include <Dialogs.h>
  30. #include <DiskInit.h>
  31. #include <LowMem.h>
  32. #include <Sound.h>
  33. #include <Traps.h>
  34. #include <Threads.h>
  35.  
  36. #include <fp.h>
  37. #include <PLStringFuncs.h>
  38.  
  39. #include <stdio.h>
  40. #include <string.h>
  41.  
  42. #if __profile__
  43. #include <Profiler.h>
  44. #endif
  45.  
  46. #include "CloseViewMP.h"
  47.  
  48. /**\
  49. |**| ==============================================================================
  50. |**| TYPEDEFS, STRUCTS, DEFINES, ENUMS, ETC.
  51. |**| ==============================================================================
  52. \**/
  53.  
  54. #if DEBUGSTRINGS
  55. #    define DEBUGSTR(x) DebugStr((x))
  56. #    define LOGSTRING(b,s) if (b) do {DEBUGSTR(s);} while (false);
  57. #else
  58. #    define DEBUGSTR(x)
  59. #    define LOGSTRING(b,s)
  60. #endif
  61.  
  62. #define RECT_WIDTH(r) ((r).right - (r).left)
  63. #define RECT_HEIGHT(r) ((r).bottom - (r).top)
  64.  
  65. #ifndef MIN
  66. #    define ABS(x)    ((x) >= 0 ? (x) : -(x))
  67. #    define MIN(a,b) ((a) < (b) ? (a) : (b))
  68. #    define MAX(a,b) ((a) > (b) ? (a) : (b))
  69. #    define PIN(a,b,c) MIN(MAX((a),(b)),(c))
  70. #endif
  71.  
  72. /**\
  73. |**| ==============================================================================
  74. |**| EXTERNAL FUNCTION PROTOTYPES
  75. |**| ==============================================================================
  76. \**/
  77.  
  78. /**\
  79. |**| ==============================================================================
  80. |**| PRIVATE FUNCTION PROTOTYPES
  81. |**| ==============================================================================
  82. \**/
  83.  
  84. static OSErr Init_Mac(void);
  85. static void Handle_Command(SInt32 ms);
  86. static void Handle_Event(const EventRecord *pEventPtr);
  87. static void Handle_NullEvent(const EventRecord *pEventPtr);
  88. static void Handle_MouseEvent(const EventRecord *pEventPtr);
  89. static void Handle_KeyEvent(char key,SInt16 modifiers);
  90. static void Handle_UpdateEvent(WindowPtr updateWindowP);
  91. static void Handle_ActivateEvent(WindowPtr updateWindowP);
  92. #if !TARGET_API_MAC_CARBON
  93. static void Handle_DiskEvent(SInt32 message);
  94. #endif !TARGET_API_MAC_CARBON
  95. static void Handle_OSEvent(const EventRecord *pEventPtr);
  96. static void Handle_ContentClick(WindowPtr pWindowPtr,const EventRecord *pEventPtr);
  97.  
  98. static Boolean SetUp_MenuBar(void);
  99. static void Adjust_MenuItems(void);
  100.  
  101. #if !TARGET_API_MAC_CARBON
  102. static void DoZoomWindow(WindowPtr pWindowPtr, short zoomDir, short hMax, short vMax);
  103. static void DoGrowWindowGrid(WindowPtr pWindowPtr);
  104. static void DoDragWindowGrid(WindowPtr pWindowPtr, Point pPoint);
  105. #endif !TARGET_API_MAC_CARBON
  106.  
  107. /**\
  108. |**| ==============================================================================
  109. |**| PRIVATE GLOBALS
  110. |**| ==============================================================================
  111. \**/
  112.  
  113. WindowPtr    gWindowPtr = nil;
  114. Rect        gWindowRect;
  115. Boolean        gInBackGround = false;
  116. //Rect         gMenuRect = {0,0,0,0};
  117. static Boolean gQuitFlag = false;
  118.  
  119. static const RGBColor
  120.                 blackRGBColor    = {0x0000,0x0000,0x0000}, 
  121.                 blueRGBColor    = {0x0000,0x0000,0xFFFF},
  122.                 ltBlueRGBColor    = {0x7FFF,0x7FFF,0xFFFF},
  123.                 dkBlueRGBColor    = {0x0000,0x0000,0x7FFF},
  124.                 redRGBColor        = {0xFFFF,0x0000,0x0000},
  125.                 greenRGBColor    = {0x0000,0xFFFF,0x0000},
  126.                 yellowRGBColor    = {0xFFFF,0xFFFF,0x0000},
  127.                 dkGrayRGBColor    = {0x4444,0x4444,0x4444},
  128.                 whiteRGBColor    = {0xFFFF,0xFFFF,0xFFFF};
  129.  
  130. static RgnHandle     gMouseRgnHdl = nil;
  131. static RgnHandle     gTempRgnHdl = nil;
  132.  
  133. static EventRecord    gTheEvent;                        // from the main event loop
  134. static Boolean        gHasColorQD = true;
  135. static Point        gGridSize = {8,4};
  136.  
  137. /**\
  138. |**| ==============================================================================
  139. |**| PRIVATE FUNCTIONS
  140. |**| ==============================================================================
  141. \**/
  142.  
  143. void main(void)
  144. {
  145. #if __profile__
  146.     if (!ProfilerInit(collectDetailed,bestTimeBase,20,5))
  147.     {
  148. #endif
  149.  
  150.     if (!Init_Mac() && SetUp_MenuBar() && !CVMP_Init(1))
  151.     {
  152.         do
  153.         {
  154.             if (gMouseRgnHdl == nil)
  155.             {
  156.                 Rect tRect = {-1,-1,1,1};
  157.  
  158.                 gMouseRgnHdl = NewRgn();
  159.                 RectRgn(gMouseRgnHdl,&tRect);
  160.             }
  161.  
  162.             InitCursor();
  163.             WaitNextEvent(everyEvent,&gTheEvent,GetCaretTime(),gMouseRgnHdl);
  164.             Handle_Event(&gTheEvent);
  165.         }
  166.         while (!gQuitFlag);
  167.  
  168.         CVMP_Term();
  169.     }
  170. #if __profile__
  171.     }
  172.     ProfilerDump("\pµApp.dump");
  173.     ProfilerTerm();
  174. #endif
  175. }
  176.  
  177. /**\
  178. |**|    Initialize toolboxes
  179. \**/
  180.  
  181. static OSErr Init_Mac(void)
  182. {
  183.     //
  184.     //    Test the computer to be sure we can do color.  
  185.     //    If not we would crash, which would be bad.  
  186.     //    If we can’t run, just beep and exit.
  187.     //
  188. #if !TARGET_API_MAC_CARBON
  189.     OSErr        error;
  190.     SysEnvRec    theWorld;
  191.  
  192.     error = SysEnvirons(1, &theWorld);
  193.     if (theWorld.hasColorQD == false)
  194.     {
  195.         SysBeep(50);
  196.         ExitToShell();                    // If no color QD, we must leave.
  197.     }
  198.     
  199.     MaxApplZone();
  200.     InitGraf(&(qd.thePort));
  201.     InitFonts();
  202.     InitWindows();
  203.     InitMenus();
  204.     TEInit();
  205.     InitDialogs(nil);
  206. #endif !TARGET_API_MAC_CARBON
  207.  
  208.     InitContextualMenus();
  209.  
  210.     //
  211.     //    Make a new window for drawing in, and it must be a color window.  
  212.     //    The window is full screen size, made smaller to make it more visible.
  213.     //
  214. #if TARGET_API_MAC_CARBON
  215.     {
  216.         BitMap screenBits;
  217.         gWindowRect = GetQDGlobalsScreenBits(&screenBits)->bounds;
  218.     }
  219. #else
  220.     gWindowRect = qd.screenBits.bounds;
  221. #endif TARGET_API_MAC_CARBON
  222.     gWindowRect.top += GetMBarHeight() + 1;
  223.  
  224.     // make it 100x100
  225.     InsetRect(&gWindowRect,
  226.         (gWindowRect.right - gWindowRect.left - 100) >> 1,
  227.         (gWindowRect.bottom - gWindowRect.top - 100) >> 1);
  228.  
  229.     gWindowPtr = NewCWindow(nil, &gWindowRect, "\pCloseViewMP!", true, zoomDocProc, 
  230.                         (WindowPtr) -1, true, 0);
  231.  
  232.     if (gWindowPtr)
  233. #if TARGET_API_MAC_CARBON
  234.         {
  235.             if (nil == gTempRgnHdl)
  236.                 gTempRgnHdl = NewRgn();
  237.  
  238.             GetWindowRegion(gWindowPtr,kWindowContentRgn,gTempRgnHdl);
  239.             GetRegionBounds(gTempRgnHdl,&gWindowRect);
  240.         }
  241. #else
  242.         gWindowRect = (*((WindowPeek) gWindowPtr)->contRgn)->rgnBBox;
  243. #endif TARGET_API_MAC_CARBON
  244.  
  245.     SetPortWindowPort(gWindowPtr);            // set window to current graf port
  246.     TextSize(kTextSize);                    // smaller font for drawing.
  247.  
  248.     {
  249.         short familyID;
  250.         GetFNum("\pMonaco",&familyID);
  251.         TextFont(familyID);
  252.     }
  253.  
  254.     return noErr;
  255. }
  256.  
  257. /**\
  258. |**|    Menu hooks
  259. \**/
  260. #ifdef HellFrozenOver
  261. static pascal short MyMBarHook(Rect *menuRect)
  262. {
  263. //    RgnHandle tempRgn = NewRgn();
  264.  
  265.     gMenuRect = *menuRect;
  266.  
  267. //    RectRgn(tempRgn,menuRect);
  268. //    CalcVisBehind(LMGetWindowList(),tempRgn);
  269. //    InvertRgn(tempRgn);
  270.  
  271.     //YieldToAnyThread();
  272. //    DisposeRgn(tempRgn);
  273.     return 0;
  274. }
  275.  
  276. static pascal void MyMenuHook(void)
  277. {    
  278. //    RgnHandle tempRgn = NewRgn();
  279. //    RectRgn(tempRgn,&gMenuRect);
  280. //    CalcVisBehind(LMGetWindowList(),tempRgn);
  281. //    InvertRgn(tempRgn);
  282.  
  283.     //YieldToAnyThread();
  284. //    DisposeRgn(tempRgn);
  285. }
  286. #endif HellFrozenOver
  287.  
  288. /**\
  289. |**|    Setup menu bar
  290. \**/
  291.  
  292. static Boolean SetUp_MenuBar(void)
  293. {
  294.     Handle mBar = GetNewMBar(128);    // handle to menu bar resource
  295.     Boolean result = false;
  296.  
  297.     if (!ResError() && mBar)
  298.     {
  299.         SetMenuBar(mBar);
  300.         AppendResMenu(GetMenuHandle(mAppleMenu),'DRVR');
  301.         DrawMenuBar();
  302.         ReleaseResource(mBar);
  303.         Adjust_MenuItems();
  304.  
  305. //        LMSetMBarHook(NewMBarHookProc(MyMBarHook));
  306. //        LMSetMenuHook(NewMenuHookProc(MyMenuHook));
  307.  
  308.         result = true;
  309.     }
  310.     return result;
  311. }
  312.  
  313. /**\
  314. |**|    Adjust menu items
  315. \**/
  316.  
  317. static void Adjust_MenuItems(void)
  318. {
  319.     MenuHandle tMenuHdl = GetMenuHandle(mMagMenu);
  320.     if (tMenuHdl)
  321.     {
  322.         UInt16 index,count = CountMenuItems(tMenuHdl);
  323.         for (index = 1;index <= count;index++)
  324.             CheckMenuItem(tMenuHdl, index, index == gMag);
  325.     }
  326. }
  327.  
  328. /**\
  329. |**|    handle menu command
  330. \**/
  331.  
  332. static void Handle_Command(SInt32 ms)
  333. {
  334.     short    menuID = ms >> 16,
  335.             menuItem = ms & 0xFFFF;
  336.  
  337.     switch (menuID)
  338.     {
  339.         case    mAppleMenu:
  340.             switch (menuItem)
  341.             {
  342.                 case iAboutBox:        // Bring up alert for About.
  343.                     SysBeep(15);
  344.                     break;
  345.                 default:            // All non-About items in this menu are DAs.
  346. #if !TARGET_API_MAC_CARBON
  347.                     {
  348.                         Str255    daName;
  349.                         GetMenuItemText(GetMenuHandle(menuID),menuItem,daName);
  350.                         OpenDeskAcc(daName);
  351.                     }
  352. #endif !TARGET_API_MAC_CARBON
  353.                     break;
  354.             }
  355.             break;
  356.         case    mFileMenu:
  357.             switch (menuItem)
  358.             {
  359.                 case iQuit:
  360.                     gQuitFlag = true;
  361.                     break;
  362.                 default:
  363.                     SysBeep(15);
  364.                     break;
  365.             }
  366.             break;
  367.         case    mMagMenu:
  368.             CVMP_SetMag(menuItem);
  369.             break;
  370.         case    mWeightMenu:        // Weight Menu
  371.             CVMP_SetWeight(menuItem);
  372.             break;
  373.     }
  374. }
  375.  
  376. /**\
  377. |**|    handle event
  378. \**/
  379.  
  380. static void Handle_Event(const EventRecord *pEventPtr)
  381. {
  382.     switch (pEventPtr->what)
  383.     {
  384.         case nullEvent:        // 0
  385.             LOGSTRING(0,"\p|pHandle_Event-I-Debug, nullEvent.;g");
  386.             Handle_NullEvent(pEventPtr);
  387.             break;
  388.         case mouseDown:        // 1
  389.             LOGSTRING(0,"\p|pHandle_Event-I-Debug, mouseDown.;g");
  390.             Handle_MouseEvent(pEventPtr);
  391.             break;
  392.         case mouseUp:        // 2
  393.             LOGSTRING(0,"\p|pHandle_Event-I-Debug, mouseUp.;g");
  394.             break;
  395.         case keyDown:        // 3
  396.             LOGSTRING(0,"\p|pHandle_Event-I-Debug, keyDown.;g");
  397.             goto dokey;
  398.         case keyUp:            // 4
  399.             LOGSTRING(0,"\p|pHandle_Event-I-Debug, keyUp.;g");
  400.             break;
  401.         case autoKey:        // 5
  402.             LOGSTRING(0,"\p|pHandle_Event-I-Debug, autoKey.;g");
  403. dokey:
  404.             Handle_KeyEvent((char)(pEventPtr->message & charCodeMask),pEventPtr->modifiers);
  405.         case updateEvt:        // 6
  406.             LOGSTRING(0,"\p|pHandle_Event-I-Debug, updateEvt.;g");
  407.             Handle_UpdateEvent((WindowPtr)pEventPtr->message);
  408.             break;
  409. #if !TARGET_API_MAC_CARBON
  410.         case diskEvt:        // 7
  411.             LOGSTRING(0,"\p|pHandle_Event-I-Debug, diskEvt.;g");
  412.             Handle_DiskEvent(pEventPtr->message);
  413.             break;
  414. #endif TARGET_API_MAC_CARBON
  415.         case activateEvt:    // 8
  416.             LOGSTRING(0,"\p|pHandle_Event-I-Debug, activateEvt.;g");
  417.             Handle_ActivateEvent((WindowPtr) pEventPtr->message);
  418.             break;
  419.         case osEvt:            // 15
  420.             LOGSTRING(0,"\p|pHandle_Event-I-Debug, osEvt.;g");
  421.             Handle_OSEvent(pEventPtr);
  422.             break;
  423.         case kHighLevelEvent:    // 23
  424.             LOGSTRING(0,"\p|pHandle_Event-I-Debug, kHighLevelEvent.;g");
  425.             AEProcessAppleEvent(pEventPtr);
  426.             break;
  427.         default:
  428.             DEBUGSTR("\p|pHandle_Event-I-Debug, UnHandled Event.;g");
  429.             break;
  430.     }
  431. }
  432.  
  433. /**\
  434. |**|    handle null event
  435. \**/
  436.  
  437. static void Handle_NullEvent(const EventRecord *pEventPtr)
  438. {
  439.     (pEventPtr);    // #pragma unused (pEventPtr)
  440.     if (gWindowPtr)
  441.     {
  442.         Rect    tRect = {40,20,52,128};
  443.         const RGBColor blackRGBColor = {0,0,0}, yellowRGBColor = {255,255,0};
  444.         GrafPtr savePort;
  445.  
  446.         GetPort(&savePort);
  447.         SetPortWindowPort(gWindowPtr);
  448.  
  449. #if TARGET_API_MAC_CARBON
  450.         {
  451.             if (nil == gTempRgnHdl)
  452.                 gTempRgnHdl = NewRgn();
  453.  
  454.             GetWindowRegion(gWindowPtr,kWindowContentRgn,gTempRgnHdl);
  455.             GetRegionBounds(gTempRgnHdl,&gWindowRect);
  456.         }
  457. #else
  458.         gWindowRect = (*((WindowPeek) gWindowPtr)->contRgn)->rgnBBox;
  459. #endif TARGET_API_MAC_CARBON
  460.  
  461.         CVMP_DoNull();
  462.  
  463.         SetPort(savePort);
  464.     }
  465. }
  466.  
  467. /**\
  468. |**|    handle mousedown event
  469. \**/
  470.  
  471. static void Handle_MouseEvent(const EventRecord *pEventPtr)
  472. {
  473.     WindowPtr            window;
  474.     short                part;
  475.  
  476.     CVMP_Update();            // Force a demand refresh to give that smooth look.
  477.  
  478.     part = FindWindow(pEventPtr->where,&window);
  479.  
  480.     if (part != inContent)
  481. #if TARGET_API_MAC_CARBON
  482.     {
  483.         Cursor arrowCursor;
  484.         SetCursor(GetQDGlobalsArrow(&arrowCursor));
  485.     }
  486. #else
  487.         SetCursor(&qd.arrow);
  488. #endif TARGET_API_MAC_CARBON
  489.  
  490.     switch(part)
  491.     {
  492.         case inContent:
  493.             Handle_ContentClick(window,pEventPtr);
  494.             break;
  495.  
  496.         case inDrag:
  497.             CVMP_Pause(true);
  498. #if TARGET_API_MAC_CARBON
  499.             {
  500.                 BitMap    screenBits;
  501.                 Rect    dragLimits = GetQDGlobalsScreenBits(&screenBits)->bounds;
  502.  
  503.                 DragWindow(window, pEventPtr->where,&dragLimits);
  504.             }
  505. #else
  506.             DoDragWindowGrid(window, pEventPtr->where);
  507. #endif TARGET_API_MAC_CARBON
  508.             break;
  509.  
  510.         case inGoAway:
  511.             if (TrackGoAway(window,pEventPtr->where))
  512.             {
  513.                 CVMP_Pause(true);
  514.                 DisposeWindow(window);
  515.                 if (window == gWindowPtr)
  516.                     gWindowPtr = nil;
  517.             }
  518.             break;
  519.  
  520.         case inGrow:
  521.             CVMP_Pause(true);
  522. #if TARGET_API_MAC_CARBON
  523.             {
  524.                 BitMap    screenBits;
  525.                 Rect    growLimits = GetQDGlobalsScreenBits(&screenBits)->bounds;
  526.                 long aLong = GrowWindow(window, pEventPtr->where,&growLimits);
  527.                 if (0 != aLong)
  528.                     SizeWindow(window,aLong & 0xFFFF,aLong >> 16,true);
  529.             }
  530. #else
  531.             DoGrowWindowGrid(window);
  532. #endif TARGET_API_MAC_CARBON
  533.             break;
  534.  
  535.         case inMenuBar:        // Process mouse menu command (if any).
  536.             {
  537.                 SInt32 ms;
  538.  
  539.                 Adjust_MenuItems();
  540.                 ms = MenuSelect(pEventPtr->where);
  541.                 if (ms)
  542.                     Handle_Command(ms);
  543.                 HiliteMenu(0);        // Unhighlight what MenuSelect hilited.
  544.             }
  545.             break;
  546. #if !TARGET_API_MAC_CARBON
  547.         case inSysWindow:    // Let the system handle the mouseDown.
  548.             SystemClick(pEventPtr,window);
  549.             break;
  550. #endif TARGET_API_MAC_CARBON
  551.  
  552.         case inZoomIn:
  553.         case inZoomOut:
  554.             {
  555. #if TARGET_API_MAC_CARBON
  556.                 BitMap    screenBits;
  557.                 Rect    zoomLimits = GetQDGlobalsScreenBits(&screenBits)->bounds;
  558. #else
  559.                 Rect zoomLimits = qd.screenBits.bounds;
  560. #endif TARGET_API_MAC_CARBON
  561.  
  562.                 CVMP_Pause(true);
  563. #if TARGET_API_MAC_CARBON
  564.                 ZoomWindow(window, part,true);
  565. #else
  566.                 DoZoomWindow(window, part,
  567.                     RECT_WIDTH(zoomLimits),
  568.                     RECT_HEIGHT(zoomLimits));
  569. #endif TARGET_API_MAC_CARBON
  570.             }
  571.             break;
  572.  
  573.         default:
  574.             break;
  575.     }
  576.  
  577.     if (gWindowPtr == window)
  578. #if TARGET_API_MAC_CARBON
  579.     {
  580.         if (nil == gTempRgnHdl)
  581.             gTempRgnHdl = NewRgn();
  582.  
  583.         GetWindowRegion(gWindowPtr,kWindowContentRgn,gTempRgnHdl);
  584.         GetRegionBounds(gTempRgnHdl,&gWindowRect);
  585.     }
  586. #else
  587.         gWindowRect = (*((WindowPeek) gWindowPtr)->contRgn)->rgnBBox;
  588. #endif TARGET_API_MAC_CARBON
  589.  
  590. //    SetRect(&gMenuRect, 0, 0, 0, 0);
  591. }
  592.  
  593. /**\
  594. |**|    handle key events
  595. \**/
  596.  
  597. static void Handle_KeyEvent(char key,SInt16 modifiers)
  598. {
  599.     if ((modifiers & cmdKey) != 0)
  600.     {
  601.         Adjust_MenuItems();
  602.         Handle_Command(MenuKey(key));
  603.         HiliteMenu(0);        // Unhighlight what MenuSelect hilited.
  604.     }
  605. }
  606.  
  607. /**\
  608. |**|    handle update events
  609. \**/
  610.  
  611. static void Handle_UpdateEvent(WindowPtr updateWindowP)
  612. {
  613.     GrafPtr savePort;
  614.  
  615.     GetPort(&savePort);
  616.     SetPortWindowPort(updateWindowP);
  617.     BeginUpdate(updateWindowP);
  618.  
  619.     if (updateWindowP == gWindowPtr)
  620.     {
  621.  
  622.     }
  623. #ifdef HellFrozenOver
  624.     DrawControls(updateWindowP);
  625. #else
  626. //    UpdateControls(updateWindowP,updateWindowP->visRgn);
  627. #endif
  628.     DrawGrowIcon(updateWindowP);
  629.     EndUpdate(updateWindowP);
  630.  
  631.     SetPort(savePort);
  632. }
  633.  
  634. /**\
  635. |**|    handle disk events
  636. \**/
  637. #if !TARGET_API_MAC_CARBON
  638. static void Handle_DiskEvent(SInt32 message)
  639. {
  640.     Point dialogLocation = {100,100};
  641.  
  642.     if ((message & 0xFFFF0000) != noErr)
  643.     {
  644.         DIBadMount(dialogLocation,message);
  645.     }
  646. }
  647. #endif !TARGET_API_MAC_CARBON
  648.  
  649. /**\
  650. |**|    handle Activate events
  651. \**/
  652.  
  653. static void Handle_ActivateEvent(WindowPtr updateWindowP)
  654. {
  655. #pragma unused(updateWindowP)
  656. }
  657.  
  658. /**\
  659. |**|    handle OS events
  660. \**/
  661.  
  662. static void Handle_OSEvent(const EventRecord *pEventPtr)
  663. {
  664.     UInt32 message = pEventPtr->message;
  665.     if ((message >> 24) == suspendResumeMessage)
  666.     {
  667.         LOGSTRING(0,"\p|Handle_OSEvent-I-Debug, suspendResumeMessage.;g");
  668.         if ((message & resumeFlag) != 0)
  669.             gInBackGround = false;
  670.         else
  671.             gInBackGround = true;
  672.     }
  673.     else if ((message >> 24) == mouseMovedMessage)
  674.     {
  675.         Rect tRect = {-1,-1,1,1};
  676.  
  677.         LOGSTRING(0,"\p|Handle_OSEvent-I-Debug, mouseMovedMessage.;g");
  678.  
  679.         OffsetRect(&tRect,pEventPtr->where.h,pEventPtr->where.v);
  680.         RectRgn(gMouseRgnHdl,&tRect);
  681.         CVMP_SetMidPoint(pEventPtr->where);
  682.         CVMP_Update();        // Tickle the blit task.
  683.     }
  684. }
  685.  
  686. /**\
  687. |**|    handle mouse down in window content
  688. \**/
  689.  
  690. static void Handle_ContentClick(WindowPtr pWindowPtr,const EventRecord *pEventPtr)
  691. {
  692. #pragma unused (pEventPtr)
  693.     if (pWindowPtr != FrontWindow())
  694.         SelectWindow(pWindowPtr);
  695.     else
  696.         CVMP_DoClick(pEventPtr);
  697. }
  698.  
  699. /**\
  700. |**|    return the rectangle for the screen that contains the most of the rectangle
  701. \**/
  702.  
  703. static Rect GetMajorScreenRect(Rect *pRectPtr)
  704. {
  705.     Rect        result;
  706.     GDHandle    dominantGDevice = nil;
  707.  
  708.     /*
  709.      *    Color QuickDraw implies the possibility of multiple monitors. 
  710.      *  One should move the rect onto the monitor containing the greatest
  711.      *    portion of the rect. This requires walking the gDevice list.
  712.      */
  713.  
  714.     if (gHasColorQD)
  715.     {
  716.         Rect                theSect;
  717.         GDHandle            nthDevice;
  718.         long                sectArea, greatestArea;
  719.  
  720.         greatestArea = 0;
  721.         for (nthDevice = DMGetFirstScreenDevice(true);nthDevice;
  722.             nthDevice = DMGetNextScreenDevice(nthDevice,true))
  723.         {
  724.             SectRect(pRectPtr, &(**nthDevice).gdRect, &theSect);
  725.             sectArea = (long) RECT_WIDTH(theSect) * (long) RECT_HEIGHT(theSect);
  726.             if (sectArea > greatestArea) {
  727.                 greatestArea = sectArea;        // save the greatest intersection
  728.                 dominantGDevice = nthDevice;    // and which device it belongs to
  729.             }
  730.         }
  731.     }
  732.  
  733.     /*
  734.      *    At this point, we know the dimensions of our rectangle, and we know
  735.      *    what screen we're going to put it on. To be more specific, however, we need a
  736.      *    rectangle which defines the maximum dimensions of the rectangle.
  737.      *
  738.      *    This rectangle accounts for the thickness of the window frame, the menu bar, and
  739.      *    one or two pixels around the edges for cosmetic reasons.
  740.      */
  741.  
  742.     if (dominantGDevice != nil)
  743.     {
  744.         result = (**dominantGDevice).gdRect;
  745.         if (dominantGDevice == GetMainDevice())        // account for menu bar on main device
  746.             result.top += GetMBarHeight();
  747.     }
  748.     else
  749.     {
  750. #if TARGET_API_MAC_CARBON
  751.         BitMap    screenBits;
  752.  
  753.         result = GetQDGlobalsScreenBits(&screenBits)->bounds;
  754. #else
  755.         result = qd.screenBits.bounds;                // if no gDevice, use default monitor
  756. #endif TARGET_API_MAC_CARBON
  757.         result.top += GetMBarHeight();
  758.     }
  759.     return result;
  760. }
  761.  
  762. /**\
  763. |**|    Pin the first rect into the second
  764. \**/
  765.  
  766. static void PinRectInRect(Rect *pRect1,const Rect *pRect2)
  767. {
  768.     if (pRect1->left < pRect2->left)
  769.     {
  770.         OffsetRect(pRect1,pRect2->left - pRect1->left,0);
  771.         if (pRect1->right > pRect2->right)
  772.             pRect1->right = pRect2->right;
  773.     }
  774.     else if (pRect1->right > pRect2->right)
  775.     {
  776.         OffsetRect(pRect1,pRect2->right - pRect1->right,0);
  777.         if (pRect1->left < pRect2->left)
  778.             pRect1->left = pRect2->left;
  779.     }
  780.  
  781.     if (pRect1->top < pRect2->top)
  782.     {
  783.         OffsetRect(pRect1,0,pRect2->top - pRect1->top);
  784.         if (pRect1->bottom > pRect2->bottom)
  785.             pRect1->bottom = pRect2->bottom;
  786.     }
  787.     else if (pRect1->bottom > pRect2->bottom)
  788.     {
  789.         OffsetRect(pRect1,0,pRect2->bottom - pRect1->bottom);
  790.         if (pRect1->top < pRect2->top)
  791.             pRect1->top = pRect2->top;
  792.     }
  793. }
  794.  
  795. #if !TARGET_API_MAC_CARBON
  796.  
  797. /**\
  798. |**|    DoZoomWindow
  799. \**/
  800.  
  801. static void DoZoomWindow(WindowPtr pWindowPtr, short zoomDir, short hMax, short vMax)
  802. {
  803.     Rect                *zoomRect;
  804.     Rect                globalPortRect, dGDRect;
  805.  
  806.     if (TrackBox(pWindowPtr, gTheEvent.where, zoomDir))
  807.     {
  808.         SetPortWindowPort(pWindowPtr);
  809.         EraseRect(&pWindowPtr->portRect);    // recommended for cosmetic reasons
  810.  
  811.         if (zoomDir == inZoomOut)
  812.         {
  813.             /*
  814.              *    ZoomWindow() is a good basic tool, but it doesn't do everything necessary to
  815.              *    implement a good human interface when zooming. In fact it's not even close for
  816.              *    more high-end hardware configurations. We must help it along by calculating an
  817.              *    appropriate window size and location any time a window zooms out.
  818.              */
  819.  
  820.             zoomRect = &(*((WindowPeek) pWindowPtr)->strucRgn)->rgnBBox;
  821.             dGDRect = GetMajorScreenRect(zoomRect);
  822.  
  823.             globalPortRect = pWindowPtr->portRect;
  824.             LocalToGlobal(&topLeft(globalPortRect));        // calculate the window's portRect
  825.             LocalToGlobal(&botRight(globalPortRect));        // in global coordinates
  826.  
  827.             // account for the window frame and inset it a few pixels
  828.             dGDRect.left    += 2 + globalPortRect.left - zoomRect->left;
  829.             dGDRect.top        += 2 + globalPortRect.top - zoomRect->top;
  830.             dGDRect.right    -= 1 + zoomRect->right - globalPortRect.right;
  831.             dGDRect.bottom    -= 1 + zoomRect->bottom - globalPortRect.bottom;
  832.  
  833.             /*
  834.              *    Now we know exactly what our limits are, and since there are input parameters
  835.              *    specifying the dimensions we'd like to see, we can move and resize the zoom
  836.              *    state rectangle for the best possible results. We have three goals in this:
  837.              *    1. Display the window entirely visible on a single device.
  838.              *    2. Resize the window to best represent the dimensions of the document itself.
  839.              *    3. Move the window as short a distance as possible to achieve #1 and #2.
  840.              */
  841.  
  842.             zoomRect = &(**(WStateDataHandle) ((WindowPeek) pWindowPtr)->dataHandle).stdState;
  843.  
  844.             /*
  845.              *    Initially set the zoom rectangle to the size requested by the input parameters,
  846.              *    although not smaller than a minimum size. We do this without moving the origin.
  847.              */
  848.  
  849.             zoomRect->right = (zoomRect->left = globalPortRect.left) + hMax;
  850. //                                    MAX(hMax, MinWindowWidth(pWindowPtr));
  851.             zoomRect->bottom = (zoomRect->top = globalPortRect.top) + vMax;
  852. //                                    MAX(vMax, MinWindowHeight(pWindowPtr));
  853.  
  854.             // Shift the entire rectangle if necessary to bring its origin inside dGDRect.
  855.             OffsetRect(zoomRect,
  856.                         MAX(dGDRect.left - zoomRect->left, 0),
  857.                         MAX(dGDRect.top - zoomRect->top, 0));
  858.  
  859.             /*
  860.              *    Shift the rectangle up and/or to the left if necessary to accomodate the view,
  861.              *    and if it is possible to do so. The rectangle may not be moved such that its
  862.              *    origin would fall outside of dGDRect.
  863.              */
  864.  
  865.             OffsetRect(zoomRect,
  866.                         -PIN(zoomRect->right - dGDRect.right, 0, zoomRect->left - dGDRect.left),
  867.                         -PIN(zoomRect->bottom - dGDRect.bottom, 0, zoomRect->top - dGDRect.top));
  868.  
  869.             // Clip expansion to dGDRect, in case view is larger than dGDRect.
  870.             zoomRect->right = MIN(zoomRect->right, dGDRect.right);
  871.             zoomRect->bottom = MIN(zoomRect->bottom, dGDRect.bottom);
  872.         }
  873.         ZoomWindow(pWindowPtr, zoomDir, false);        // all it needed was a brain transplant
  874.     }
  875. }    // DoZoomWindow
  876.  
  877. /**\
  878. |**|    DoGrowWindowGrid
  879. \**/
  880.  
  881. #define kExtremeNeg -32768
  882. #define kExtremePos (32767 - 1) /* required to address an old region bug, see develop 20 Q&As */
  883.  
  884. static void PullRect(Rect* startRect);    // prototype
  885. static void DoGrowWindowGrid(WindowPtr pWindowPtr)
  886. {
  887.     PenState oldPen;
  888.     WindowPtr tempWP, WMPort;
  889.     Rect draggingRect = pWindowPtr->portRect;
  890.     Rect wideOpen =    {kExtremeNeg, kExtremeNeg, kExtremePos, kExtremePos};
  891.     RgnHandle oldRgn = NewRgn();
  892.  
  893.     GetPort(&tempWP);
  894.     SetPort(pWindowPtr);
  895.  
  896.     /* normalize my rectangle into the window manager port coordinates */
  897.     LocalToGlobal((Point *) &draggingRect.top);
  898.     LocalToGlobal((Point *) &draggingRect.bottom);
  899.  
  900.     /*  go to the WManager port */
  901.     GetWMgrPort(&WMPort);
  902.     SetPort(WMPort);
  903.  
  904.     /* save the Window manager pen state since we'll be changing it */
  905.     GetPenState(&oldPen);
  906.  
  907.     /* localize back */
  908.     GlobalToLocal((Point *) &draggingRect.top);
  909.     GlobalToLocal((Point *) &draggingRect.bottom);
  910.  
  911.     /* save the current clip region, and set our wide-open clip */
  912.     GetClip(oldRgn);
  913.     ClipRect(&wideOpen);
  914.  
  915.     /* go to the routine below to do the actual dragging */
  916.     PullRect(&draggingRect);
  917.  
  918.     /* restore the original environment */
  919.     SetClip(oldRgn);
  920.     SetPenState(&oldPen);
  921.     DisposeRgn(oldRgn);
  922.  
  923.     /* now size the window for the returned rect */
  924.     SetPort(pWindowPtr);
  925.     InvalRect(&pWindowPtr->portRect);
  926.  
  927.     {
  928.         Rect tRect = GetMajorScreenRect(&(*((WindowPeek) pWindowPtr)->contRgn)->rgnBBox);
  929.         PinRectInRect(&draggingRect,&tRect);
  930.         MoveWindow(pWindowPtr,draggingRect.left,draggingRect.top,true);
  931.     }
  932.  
  933.     SizeWindow(pWindowPtr, draggingRect.right - draggingRect.left, draggingRect.bottom - draggingRect.top, true);
  934.     SetPort(tempWP);
  935. }    // DoGrowWindowGrid
  936.  
  937. static void PullRect(Rect* startRect)
  938. {
  939.     Rect oldRect;
  940.     Point endPoint;
  941.     Boolean hreversed = false;
  942.     Boolean vreversed = false;
  943.     short tempH,tempV;
  944.     short divByGridh,divByGridv;
  945.  
  946.     /* set up */
  947.     oldRect = *startRect;
  948.     PenMode(srcXor);                            /* So we can rubberband */
  949.     PenPat(&qd.gray);
  950.     FrameRect(startRect);
  951.     divByGridh = startRect->right;
  952.     divByGridv = startRect->bottom;
  953.  
  954.     while (StillDown())
  955.     {    /* Keep doing this as long as the */
  956.         /* user keeps the mouse down */
  957.  
  958.         GetMouse(&endPoint);                    /* Current mouse position in local */
  959.  
  960.         // see if it's on a  grid point
  961.         tempH = ABS(endPoint.h - divByGridh) / gGridSize.h;
  962.         tempV = ABS(endPoint.v - divByGridv) / gGridSize.v;
  963.  
  964.         // normalize to our grid values. We'll always go outwards as better
  965.         if ((tempH * gGridSize.h) != ABS(endPoint.h - divByGridh))    // shove out based on the remainer
  966.             endPoint.h = (((endPoint.h) / gGridSize.h) * gGridSize.h) + gGridSize.h;
  967.         if ((tempV * gGridSize.v) != ABS(endPoint.v - divByGridv))
  968.             endPoint.v = (((endPoint.v) / gGridSize.v) * gGridSize.v) + gGridSize.v;
  969.  
  970.         // If things reversed, we have to make sure that we don't try
  971.         // and grid the origin point of the drag, cuz that would be weird
  972.         if (hreversed)
  973.         {    /* see if the rectangle flipped first */
  974.             if (endPoint.h > startRect->right)    /* they flipped back */
  975.                 hreversed = false;                /* and ignore this move */
  976.             else    /* still reversed */
  977.                 startRect->left = endPoint.h;
  978.         }
  979.         else
  980.         {
  981.             if (endPoint.h < startRect->left)
  982.                 hreversed = true;
  983.             else
  984.                 startRect->right = endPoint.h;
  985.         }
  986.         if (vreversed)
  987.         {    /* see if it flipped first */
  988.             if (endPoint.v > startRect->bottom)    /* they flipped back */
  989.                 vreversed = false;                /* and ignore this move */
  990.             else                /* still reversed */
  991.                 startRect->top = endPoint.v;
  992.         }
  993.         else
  994.         {
  995.             if (endPoint.v < startRect->top)
  996.                 vreversed = true;
  997.             else
  998.                 startRect->bottom = endPoint.v;
  999.         }
  1000.         
  1001.         if (!EqualRect(startRect,&oldRect))
  1002.         {    /* redraw the rect only if the mouse moved */
  1003.             FrameRect(&oldRect);
  1004.             FrameRect(startRect);                /* draw the new rect */
  1005.             oldRect = *startRect;
  1006.         }
  1007.     }
  1008.     FrameRect(startRect);
  1009.  
  1010.     PenMode(srcCopy);
  1011.     PenPat(&qd.black);
  1012. }    // PullRect
  1013.  
  1014.  
  1015. /*-------------------------------------------------------------------------------------
  1016.  
  1017.     DoDragWindowGrid- a big nasty function to Drag a window along grid lines.  
  1018.     Note the elegant error handling.  You should change it to make your users happy.
  1019.     
  1020.     You can change the size of the 'grid rects' by changing the value of kIncrement.
  1021.     
  1022. */
  1023. static void DoDragWindowGrid(WindowPtr pWindowPtr, Point pPoint)
  1024. {
  1025.     RgnHandle    dragRgn, lastDragRgn, insetGray;
  1026.     GrafPtr        oldPort, tmpPort;
  1027.     Point        currPt, firstMulPoint, lastMulPoint, currMulPoint;
  1028.     Boolean        frameHidden;
  1029.     enum        {kIncrement = 16, kBorderInset = 4};
  1030.  
  1031.     // Set up our regions - init our variables.
  1032.     dragRgn = NewRgn(); 
  1033.     lastDragRgn = NewRgn(); 
  1034.     insetGray = NewRgn();
  1035.     if ((dragRgn == NULL) || (lastDragRgn == NULL) || (insetGray == NULL)) {
  1036.         DebugStr("\pnot enough memory- bye!");
  1037.         return;
  1038.     }
  1039.     CopyRgn(GetGrayRgn(), insetGray);
  1040.     if (MemError() != noErr) {
  1041.         DebugStr("\pnot enough memory- bye!");
  1042.         return;
  1043.     }
  1044.  
  1045.     InsetRgn(insetGray, kBorderInset, kBorderInset);
  1046.     frameHidden = false;
  1047.  
  1048.     // Set up a port to draw into, and save off the old
  1049.     tmpPort = (GrafPtr)NewPtr(sizeof(GrafPort));
  1050.     if (tmpPort == NULL) {
  1051.         DebugStr("\pnot enough memory- bye!");
  1052.         return;
  1053.     }
  1054.     GetPort(&oldPort);
  1055.     OpenPort(tmpPort);
  1056.     CopyRgn(GetGrayRgn(), tmpPort->visRgn);
  1057.     if (MemError() != noErr) {
  1058.         DebugStr("\pnot enough memory- bye!");
  1059.         return;
  1060.     }
  1061.     tmpPort->portRect = (*GetGrayRgn())->rgnBBox;
  1062.     SetPort(tmpPort);
  1063.     
  1064.     PenMode(patXor);
  1065.     PenPat(&qd.gray);
  1066.  
  1067.     // Set the incoming point to be on a multiple of kIncrement,
  1068.     // to make later calculations easier.
  1069.     currMulPoint.h = pPoint.h + (kIncrement/2);
  1070.     currMulPoint.h /= kIncrement; currMulPoint.h *= kIncrement;
  1071.     currMulPoint.v = pPoint.v + (kIncrement/2);
  1072.     currMulPoint.v /= kIncrement; currMulPoint.v *= kIncrement;
  1073.  
  1074.     firstMulPoint = lastMulPoint = currMulPoint;
  1075.  
  1076.     CopyRgn(((WindowPeek)pWindowPtr)->strucRgn, dragRgn);
  1077.     if (MemError() != noErr) {
  1078.         DebugStr("\pnot enough memory- bye!");
  1079.         return;
  1080.     }
  1081.  
  1082.     CopyRgn(((WindowPeek)pWindowPtr)->strucRgn, lastDragRgn);
  1083.     if (MemError() != noErr) {
  1084.         DebugStr("\pnot enough memory- bye!");
  1085.         return;
  1086.     }
  1087.  
  1088.     // Draw the first framed region, which will follow the mouse
  1089.     // on the screen
  1090.     FrameRgn(lastDragRgn);
  1091.  
  1092.     while (WaitMouseUp() == true) {
  1093.         // Now track the mouse, and when it moves enough make the framed
  1094.         // region move as well.
  1095.         GetMouse(&currPt);
  1096.     
  1097.         // Set the new point to be on a multiple of kIncrement
  1098.         currMulPoint.h = currPt.h + (kIncrement/2);
  1099.         currMulPoint.h /= kIncrement; currMulPoint.h *= kIncrement;
  1100.         currMulPoint.v = currPt.v + (kIncrement/2);
  1101.         currMulPoint.v /= kIncrement; currMulPoint.v *= kIncrement;
  1102.  
  1103.         // Should we be showing the frame region ??
  1104.         if (PtInRgn(currPt, insetGray) == false) {
  1105.             // It's somewhere near the edges, so hide the frame
  1106.             if (frameHidden == false)    // if it's not hidden already, hide it now
  1107.                 FrameRgn(lastDragRgn);
  1108.             frameHidden = true;
  1109.         }
  1110.         else {    // else, the frame should be shown if it's hidden
  1111.             if (frameHidden == true) {
  1112.                 FrameRgn(lastDragRgn);
  1113.                 frameHidden = false;
  1114.             }
  1115.         }
  1116.     
  1117.         // Has the mouse moved ?
  1118.         if (!EqualPt(currMulPoint,lastMulPoint)) {
  1119.             // The mouse coordinates have changed enough to adjust the window,
  1120.             // so move the frame accordingly
  1121.             OffsetRgn(dragRgn, currMulPoint.h - lastMulPoint.h, currMulPoint.v - lastMulPoint.v);
  1122.  
  1123.             if (frameHidden == false) {
  1124.                 // Only show the frame if we're allowed to.
  1125.                 FrameRgn(dragRgn);        
  1126.                 FrameRgn(lastDragRgn);
  1127.             }
  1128.             lastMulPoint = currMulPoint;
  1129.             CopyRgn(dragRgn, lastDragRgn);
  1130.             if (MemError() != noErr) {
  1131.                 DebugStr("\pnot enough memory- bye!");
  1132.                 return;
  1133.             }
  1134.         }    
  1135.     }
  1136.     
  1137.     // If frameHidden is true, there's no need to erase the final frame.
  1138.     if (frameHidden == false)
  1139.         FrameRgn(lastDragRgn);
  1140.  
  1141.     if (!EqualPt(lastMulPoint,firstMulPoint) && (frameHidden == false)) {
  1142.         // The mouse has moved from its original position and is
  1143.         // somewhere on the screen, so move the window accordingly.
  1144.         Point    globalPt, diffPt, contPt = {0, 0};
  1145.  
  1146.         // Calculate the difference between the strucRgn's 0, 0 and
  1147.         // the window's content region 0, 0.  Remember that MoveWindow
  1148.         // moves the window's *content* to the coordinate specified, and
  1149.         // we want to move the window's structure to fit in the lastDragRgn
  1150.         SetPort(pWindowPtr);
  1151.         // LocalToGlobal works much better when the port is set up...
  1152.         LocalToGlobal(&contPt);
  1153.         SetPort(tmpPort);
  1154.         diffPt.h = contPt.h - (*((WindowPeek)pWindowPtr)->strucRgn)->rgnBBox.left;
  1155.         diffPt.v = contPt.v - (*((WindowPeek)pWindowPtr)->strucRgn)->rgnBBox.top;
  1156.         
  1157.         globalPt.h = (*lastDragRgn)->rgnBBox.left;
  1158.         globalPt.v = (*lastDragRgn)->rgnBBox.top;
  1159.         LocalToGlobal(&globalPt);
  1160.         globalPt.h += diffPt.h;
  1161.         globalPt.v += diffPt.v;
  1162.         MoveWindow(pWindowPtr, globalPt.h, globalPt.v, true);
  1163.     }
  1164.  
  1165.     {
  1166.         Rect wRect = (*((WindowPeek) pWindowPtr)->contRgn)->rgnBBox;
  1167.         Rect tRect = GetMajorScreenRect(&wRect);
  1168.         PinRectInRect(&wRect,&tRect);
  1169.         MoveWindow(pWindowPtr,wRect.left,wRect.top,true);
  1170. //        SizeWindow(pWindowPtr, wRect.right - wRect.left, wRect.bottom - wRect.top, true);
  1171.     }
  1172.  
  1173.     // Close the port and tear everything down
  1174.     ClosePort(tmpPort);
  1175.     SetPort(oldPort);
  1176.     DisposeRgn(dragRgn);
  1177.     DisposeRgn(insetGray);
  1178.     DisposeRgn(lastDragRgn);
  1179. }    // DoDragWindowGrid
  1180. #endif !TARGET_API_MAC_CARBON
  1181.